import React from 'react';
import _ from 'lodash';
// import moment from 'moment';
import {
    Modal,
    Form,
    Spin,
    Cascader,
    Input,
    InputNumber,
    TimePicker,
    DatePicker,
    Select,
    Switch,
    Slider,
    Checkbox,
    Radio,
    Mention,
    Rate,
    Transfer,
    Upload
} from 'antd';

const RadioGroup = Radio.Group;
const Option = Select.Option;
const FormItem = Form.Item;
const createInput = (props = {}, type) => {
    switch (type) {
        case 'bool': {
            return <Switch {...props} />;
        }
        case 'number': {
            return <InputNumber {...props} />;
        }
        case 'date': {
            return <DatePicker {...props} />;
        }
        case 'time': {
            return <TimePicker {...props} />;
        }
        case 'select': {
            const { data, ...other } = props;
            const items = _.map(data, (d) => {
                const { id, code, key, name, value, label } = d;
                const k = id || code || key;
                const n = name || value || label;
                return <Option key={k} value={k}>{n}</Option>;
            });
            return (
                <Select {...other}>
                    {items}
                </Select>
            );
        }
        case 'cascader': {
            return <Cascader {...props} />;
        }
        case 'slider': {
            return <Slider {...props} />;
        }
        case 'checkbox': {
            return <Checkbox {...props} />;
        }
        case 'radio': {
            const { data, ...other } = props;
            const items = _.map(data, (d) => {
                const { id, code, key, name, value, label } = d;
                const k = id || code || key;
                const n = name || value || label;
                return <Radio key={k} value={n}>{n}</Radio>;
            });
            return <RadioGroup {...other}>{items}</RadioGroup>;
        }
        case 'mention': {
            return <Mention {...props} />;
        }
        case 'rate': {
            return <Rate {...props} />;
        }
        case 'transfer': {
            return <Transfer {...props} />;
        }
        case 'upload': {
            return <Upload {...props} />;
        }
        case 'input': {
            return <Input {...props} />;
        }
        default: {
            return <Input autoComplete="off" {...props} />;
        }
    }
};
export const defaultFormItemLayout = {
    labelCol: {
        xs: { span: 8 },
        sm: { span: 6 },
        md: { span: 6 },
        lg: { span: 6 },
        xl: { span: 6 },
    },
    wrapperCol: {
        xs: { span: 14 },
        sm: { span: 14 },
        md: { span: 14 },
        lg: { span: 10 },
        xl: { span: 10 },
    },
};
const createFormItems = (props) => {
    const {
        config,
        form,
        formItemLayout = defaultFormItemLayout,
        Wrapped
    } = props;
    return _.reduce(config, (res, cfg, key) => {
        if (_.isFunction(cfg)) {
            const component = cfg(props, key);
            if (component) {
                res.push(component);
            }
        } else {
            /**
             * 生成表单组的配置项，一般在editor组件上用
             * 键名是config，以下是字段
             * @type 表单类型;
             * @input 表单dom属性;
             * @item FormItem属性;
             * @fd 表单数据属性
             * @label 表单标题
             */
            const { type, input = {}, item = {}, fd = {}, label } = cfg;
            let fdprops = {};
            switch (type) {
                case 'bool': {
                    fdprops = { valuePropName: 'checked' };
                    break;
                }
                /*case 'select': {
                    console.log('cfg', cfg);
                    break;
                }*/
            }
            const inputComponent = input && _.isFunction(input)
                ? input(props, createInput)
                : createInput(input, type);
            if (inputComponent) {
                if (_.isFunction(fd)) {
                    fdprops = { ...fdprops, ...fd(props) };
                } else {
                    fdprops = { ...fdprops, ...fd };
                }
                const component = form.getFieldDecorator(key, { ...fdprops })(inputComponent);
                const formItem = (
                    <FormItem key={key} label={label} {...formItemLayout} {...item} >
                        {component}
                    </FormItem>
                );
                if (Wrapped) {
                    res.push(<Wrapped key={key}>{formItem}</Wrapped>);
                } else {
                    res.push(formItem);
                }
            }
        }
        return res;
    }, []);
};
export const restoreValues = (values) => {
    /* status 由Boolean改为number */
    _.forIn(values, (v, k) => {
        if (k === 'status') {
            values[k] = v ? 1 : 0;
        }
        if (k === 'role') {
            const {key, label} = v;
            values[k].roleId = key;
            values[k].roleName = label;
            delete values[k].key;
            delete values[k].label;
            delete values[k].title;
        }
    });
    return values;
};
const modalForm = (props) => {
    const {
        dispatch,
        form,
        ns,
        visible,
        width,
        isNew,
        name = '',
        formHeader,
        formFooter,
        onOk,
        onCancel,
        children,
        formProps = {},
    } = props;
    const { validateFields } = form;
    const onOkDef = (values, err) => {
        if (!err) {
            console.log('提交的数据：', ns, values);
            dispatch({
                type: `${ns}/editorOk`,
                payload: {
                    values: restoreValues(values),
                    isNew,
                },
            });
        }
    };
    const onCancelDef = () => {
        dispatch({
            type: `${ns}/editorVisible`,
        });
    };
    const onOkProxy = onOk || onOkDef;
    const onCancelProxy = onCancel || onCancelDef;
    const okHandler = () => {
        validateFields((err, values) => {
            if (!err) {
                onOkProxy(values);
            } else if (!onOkProxy(null, err)) {
                //错误提示
            }
        });
    };
    const title = isNew ? `新增${name}` : `编辑${name}`;
    const header = formHeader && _.isFunction(formHeader) ? formHeader(props) : formHeader;
    const footer = formFooter && _.isFunction(formFooter) ? formFooter(props) : formFooter;
    const formItems = createFormItems(props);
    return (
        <Modal
            title={title}
            visible={visible}
            onOk={okHandler}
            onCancel={onCancelProxy}
            width={width}
            maskClosable={false}
        >
            <Spin spinning={!!props.loading} delay={0}>
                <Form
                    onSubmit={okHandler}
                    {...formProps}
                >
                    {header}
                    {formItems}
                    {footer}
                </Form>
                {children}
            </Spin>
        </Modal>
    );
};
const mapPropsToFields = (props) => {
    const {
        editorData = {},
        editorDef = {},
        editorErr = {},
        valueConvert = (val, key) => {
            switch (key) {
                case 'status': {
                    return val === 1;
                }
                case 'role': {
                    _.forIn(val, (v, k) => {
                        if (k === 'roleId') {
                            val.key = v.toString();
                            delete val[k];
                        }
                        if (k === 'roleName') {
                            val.label = v;
                            delete val[k];
                        }
                    });
                    return val;
                }
                default: {
                    return val;
                }
            }
        },
        errorConvert = res => res,
    } = props;
    const data = { ...editorDef, ...editorData };
    const fields = _.reduce(data, (res, val, key) => {
        res[key] = Form.createFormField({ value: valueConvert(val, key, data) });
        return res;
    }, {});
    return errorConvert(fields, editorErr);
};

const ModalForm = Form.create({ mapPropsToFields })(modalForm);
export default ModalForm;
